﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;

using SSS.AlphaNN.Logic;


namespace SSS.AlphaNN.Logic
{
    /// <summary>
    /// Класс нейронная сеть. Сделан как паттерн декоратор.
    /// </summary>
    public class NeuronNetwork//:INeuronNetwork<double>
    {
        

        /// <summary>
        /// значение отклонения у нейрона
        /// </summary>
        private double[] _firstValueNeuron;

        /// <summary>
        /// Функция обучения
        /// первый параметр - это значения от учителя, 
        /// второй параметр это значения входных сигналов
        /// третий параметр - это значения весов,
        /// новые веса выходной параметр
        /// </summary>
        private Func<double[], double[],double[], TypeWeight[][], TypeWeight[][]>
            _functionLearning;

        /// <summary>
        /// Функция активации
        /// </summary>
        private Func<double, double>[] _functionActivation;

        /// <summary>
        /// Обучение нейронной сети
        /// </summary>
        /// <param name="inputValue">Входные значения</param>
        /// <param name="outputValue">Выходные значения</param>
        /// <param name="count">количество обучений</param>
        /// <param name="e">погрешность при достижении которой прекратить обучение</param>
        public void Learning( TypeWeight[][] valueOutput, TypeWeight[][] valueOututDiff, TypeWeight[][] valueInput, double coefficientLearning)
        {


        }

       
       

        /// <summary>
        /// Запуск нейронной сети
        /// </summary>
        /// <param name="inputValue">Входные параметры</param>
        /// <returns>результат работы нейронной сети</returns>
        public double[] Run(TypeWeight[][] weights, double[] inputValue)
        {
            //началась магия
            int lenIn = inputValue.Length;
            int len = weights.Length;
           
            for (int i = lenIn; i < len; i++)
            {
                try
                {
                    double sum = _firstValueNeuron[i - lenIn];
                    for (int j = 0; j < i; j++)
                    {
                        if (weights[j][i - lenIn].ValueSet)
                        {
                            sum += (weights[j][i - lenIn] = (weights[j][i - lenIn] * ((j < inputValue.Length) ? inputValue[j] : 1))).Value;
                        }
                    }

                    sum = _functionActivation[i - lenIn](sum);


                    for (int j = 0; j < weights[i].Length; j++)
                    {


                        if (weights[i][j].ValueSet)
                        {
                            weights[i][j] *= sum;
                        }
                    }
                }
                catch (Exception)
                {
                    
                    throw new FormatException("Ошибка в архитектуре!");
                }
                


                
            }

            len = weights[0].Length - 1;


            return weights.Where(x => x[len].ValueSet).
                Select(x => x[len].Value).ToArray();
            //магия закончилась
        }

        //Жёсткий конструктор=)
        /// <summary>
        /// Конструктор
        /// </summary>
        /// <param name="inputWeights">Начальные веса</param>
        /// <param name="functionLearning">Функция обучения</param>
        /// <param name="summator">Сумматор</param>
        /// <param name="functionActivation">Функция активации</param>
        public NeuronNetwork(
            Func<double[], double[], double[], TypeWeight[][], TypeWeight[][]> functionLearning,
            Func<double, double>[] functionActivation, double[] firstValueNeuron)
        {
            _functionActivation = functionActivation;
            _functionLearning = functionLearning;
            _firstValueNeuron = (double[])firstValueNeuron.Clone();
        }

        public NeuronNetwork(
           Func<double, double>[] functionActivation, double[] firstValueNeuron)
        {
            _functionActivation = functionActivation;
            _firstValueNeuron =(double[]) firstValueNeuron.Clone();
            
        }
    }
}
